package com.gitee.wsl.android.ext

import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityOptions
import android.app.PendingIntent
import android.app.PendingIntent.getActivity
import android.app.PendingIntent.getBroadcast
import android.app.PendingIntent.getService
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import com.gitee.wsl.android.ext.IntentExt.DEFAULT_REQUEST_CODE
import com.gitee.wsl.android.ext.PendingIntentExt.defaultUpdateFlags
import com.gitee.wsl.android.ext.device.VersionExt.isAtLeastApiLevel
import com.gitee.wsl.ext.base.ifValue

enum class PendingIntentMode{
    ACTIVITY,BROADCAST,SERVICE
}

object PendingIntentExt {

    val immutableFlag:Int
        get() = (true).ifValue(PendingIntent.FLAG_IMMUTABLE,0)

    val defaultCancelFlags = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S).
                        ifValue(PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE,
                               PendingIntent.FLAG_CANCEL_CURRENT)

    val defaultUpdateFlags = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S).
                        ifValue(PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE,
                            PendingIntent.FLAG_UPDATE_CURRENT)

    fun build(context: Context, intent: Intent, requestCode:Int=DEFAULT_REQUEST_CODE, mode: PendingIntentMode = PendingIntentMode.ACTIVITY, config:PendingIntent.()->Unit={}): PendingIntent {
        val pendingIntent=when(mode){
            PendingIntentMode.ACTIVITY ->{
                PendingIntent.getActivity(context, requestCode, intent, defaultCancelFlags)
            }
            PendingIntentMode.BROADCAST ->{
                PendingIntent.getBroadcast(context, requestCode, intent, defaultCancelFlags)
            }
            PendingIntentMode.SERVICE ->{
                PendingIntent.getService(context, requestCode, intent, defaultCancelFlags)
            }
        }
        config(pendingIntent)
        return pendingIntent
    }

    fun build(context: Context, targetClass: Class<*>, requestCode:Int=DEFAULT_REQUEST_CODE, mode: PendingIntentMode = PendingIntentMode.ACTIVITY, config:PendingIntent.()->Unit={}): PendingIntent {
        val intent=Intent(context, targetClass)
        intent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
        return build(context, intent, requestCode, mode, config)
    }
}

fun Context.pendingIntentActivity( targetClass: Class<*>,requestCode:Int,config:PendingIntent.()->Unit={}):PendingIntent{
    return PendingIntentExt.build(
        this,
        targetClass,
        requestCode,
        PendingIntentMode.ACTIVITY,
        config
    )
}

fun Context.pendingIntentActivity(intent: Intent,requestCode:Int, config:PendingIntent.()->Unit={}):PendingIntent{
    return PendingIntentExt.build(this, intent, requestCode, PendingIntentMode.ACTIVITY, config)
}

fun Context.pendingIntentBroadcast(targetClass: Class<*>,requestCode:Int, config:PendingIntent.()->Unit={}):PendingIntent{
    return PendingIntentExt.build(
        this,
        targetClass,
        requestCode,
        PendingIntentMode.BROADCAST,
        config
    )
}

fun Context.pendingIntentBroadcast( intent: Intent,requestCode:Int,config:PendingIntent.()->Unit={}):PendingIntent{
    return PendingIntentExt.build(this, intent, requestCode, PendingIntentMode.BROADCAST, config)
}

fun Context.pendingIntentService(targetClass: Class<*>,requestCode:Int,config:PendingIntent.()->Unit={}):PendingIntent{
    return PendingIntentExt.build(this, targetClass, requestCode, PendingIntentMode.SERVICE, config)
}

fun Context.pendingIntentService(intent: Intent,requestCode:Int, config:PendingIntent.()->Unit={}):PendingIntent{
    return PendingIntentExt.build(this, intent, requestCode, PendingIntentMode.SERVICE, config)
}

@SuppressLint("UnspecifiedImmutableFlag")
inline fun <reified T : Service> Context.servicePendingIntent(
    action: String,
    configIntent: Intent.() -> Unit = {}
): PendingIntent? {
    val intent = Intent(this, T::class.java)
    intent.action = action
    configIntent.invoke(intent)
    return getService(this, 0, intent, defaultUpdateFlags)
}

@SuppressLint("UnspecifiedImmutableFlag")
fun Context.activityPendingIntent(
    intent: Intent,
    action: String
): PendingIntent? {
    intent.action = action
    return getActivity(this, 0, intent, defaultUpdateFlags)
}

@SuppressLint("UnspecifiedImmutableFlag")
inline fun <reified T : Activity> Context.activityPendingIntent(
    action: String,
    configIntent: Intent.() -> Unit = {}
): PendingIntent? {
    val intent = Intent(this, T::class.java)
    intent.action = action
    configIntent.invoke(intent)
    return getActivity(this, 0, intent, defaultUpdateFlags)
}

@SuppressLint("UnspecifiedImmutableFlag")
inline fun <reified T : BroadcastReceiver> Context.broadcastPendingIntent(
    action: String,
    configIntent: Intent.() -> Unit = {}
): PendingIntent? {
    val intent = Intent(this, T::class.java)
    intent.action = action
    configIntent.invoke(intent)
    return getBroadcast(this, 0, intent, defaultUpdateFlags)
}

fun PendingIntent.sendWithBackgroundPermission() {
    if (isAtLeastApiLevel(34)) {
        val options = ActivityOptions.makeBasic()
            .setPendingIntentCreatorBackgroundActivityStartMode(
                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
            )
            .setPendingIntentBackgroundActivityStartMode(
                ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
            )
            .toBundle()
        send(options)
    } else {
        send()
    }
}
